﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Security;
using System.Runtime.InteropServices;
using OpenRasta.Web;
using umbraco.cms.businesslogic.member;
using uREST.Core.Attributes;
using uREST.Core.Handlers;
using uREST.CMS.Extensions;

namespace uREST.CMS.Handlers
{
    [UmbracoAuthorize(Applications = "member")]
    public class MemberHandler : AbstractHandler
    {
        public MemberHandler(ICommunicationContext context)
            : base(context)
        { }

        // GET (LIST)
        [HttpOperation(ForUriName = "MemberList")]
        public OperationResult GetMemberList(
            [Optional] string username,
            [Optional] string role,
            [Optional] string memberTypeAlias)
        {
            var memberList = new List<Member>();
            memberList.AddRange(!string.IsNullOrEmpty(username)
                                    ? Member.GetMemberByName(username, false)
                                    : Member.GetAllAsList());

            if (!string.IsNullOrEmpty(role))
                memberList = memberList.Where(member => Roles.IsUserInRole(member.LoginName, role)).ToList();

            if (!string.IsNullOrEmpty(memberTypeAlias))
                memberList = memberList.Where(member => member.ContentType.Alias == memberTypeAlias).ToList();

            return new OperationResult.OK { ResponseResource = memberList.ToResourceList() };
        }

        // GET (SINGLE)
        [HttpOperation(ForUriName = "Member")]
        public OperationResult GetMember(
            [Optional] int id,
            [Optional] string username)
        {
            if(id == 0 && string.IsNullOrEmpty(username))
                return new OperationResult.BadRequest();
            
            Member member = null;

            try
            {
                member = id > 0 ?
                    new Member(id) :
                    Member.GetMemberFromLoginName(username);
            }
            catch
            { }

            if (member == null)
                return new OperationResult.NotFound();

            return new OperationResult.OK { ResponseResource = member.ToResource() };
        }

        // CREATE
        [HttpOperation(ForUriName = "MemberList")]
        public OperationResult PostMember(Resources.Member resource)
        {
            if (resource.Id > 0 || string.IsNullOrEmpty(resource.MemberTypeAlias) || string.IsNullOrEmpty(resource.Username) || string.IsNullOrEmpty(resource.Email))
                return new OperationResult.BadRequest();

            var memberType = MemberType.GetByAlias(resource.MemberTypeAlias);
            if (memberType == null)
                return new OperationResult.BadRequest();

            if (string.IsNullOrEmpty(resource.DisplayName))
                resource.DisplayName = resource.Username;

            var member = Member.MakeNew(resource.Username, resource.Email, memberType, AuthenticatedUser);
            member.Text = resource.DisplayName;
            member.Password = resource.Password;

            if (resource.Properties != null && resource.Properties.Count > 0)
            {
                foreach (var propResource in resource.Properties)
                {
                    var prop = member.getProperty(propResource.Key);
                    if (prop != null)
                        prop.Value = propResource.Value;
                }
            }

            member.Save();

            if (resource.Roles != null && resource.Roles.Any())
                Roles.AddUserToRoles(member.LoginName, resource.Roles.ToArray());

            return new OperationResult.Created { ResponseResource = member.ToResource() };
        }


        // UPDATE
        [HttpOperation(ForUriName = "Member")]
        public OperationResult PutMember(
            [Optional] int id,
            [Optional] string username, 
            Resources.Member resource)
        {
            if (id == 0 && string.IsNullOrEmpty(username))
                return new OperationResult.BadRequest();

            Member member = null;

            try
            {
                member = id > 0 ?
                    new Member(id) :
                    Member.GetMemberFromLoginName(username);
            }
            catch
            { }

            if (member == null)
                return new OperationResult.NotFound();

            member.Text = resource.DisplayName;
            member.LoginName = resource.Username;
            member.Email = resource.Email;

            if (!string.IsNullOrEmpty(resource.Password))
                member.Password = resource.Password;

            if (resource.Properties != null && resource.Properties.Count > 0)
            {
                foreach (var propResource in resource.Properties)
                {
                    var prop = member.getProperty(propResource.Key);
                    if (prop != null)
                        prop.Value = propResource.Value;
                }
            }

            member.Save();

            Roles.RemoveUserFromRoles(member.LoginName, Roles.GetRolesForUser(member.LoginName));

            if (resource.Roles != null && resource.Roles.Any())
                Roles.AddUserToRoles(member.LoginName, resource.Roles.ToArray());

            return new OperationResult.Created { ResponseResource = member.ToResource() };
        }

        // DELETE
        [HttpOperation(ForUriName = "Member")]
        public OperationResult DeleteMember(
            [Optional] int id,
            [Optional] string username)
        {
            if (id == 0 && string.IsNullOrEmpty(username))
                return new OperationResult.BadRequest();

            Member member = null;

            try
            {
                member = id > 0 ?
                    new Member(id) :
                    Member.GetMemberFromLoginName(username);
            }
            catch
            { }

            if (member == null)
                return new OperationResult.NotFound();

            try
            {
                member.delete();
                return new OperationResult.NoContent();
            }
            catch
            {
                return new OperationResult.InternalServerError();
            }
        }
    }
}
